package com.jxf.demo.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.jxf.demo.dto.*;
import com.jxf.demo.service.AbstractDXFParseService;
import com.jxf.demo.util.PolygonFixUtils;
import org.kabeja.dxf.DXFLine;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

import static com.jxf.demo.util.PolygonFixUtils.fixPolygon;

/**
 * 线段解析Service
 */
@Service
public class DXFLineParseService extends AbstractDXFParseService {

    @Override
    public List<DXFPointInfo> doParse(List lineEntities) {

        return parseLine(lineEntities);
    }

    @Override
    public String getType() {
        return "LINE";
    }

    private List<DXFPointInfo> parseLine2(List lineEntities) {
        List<DXFPointInfo> list = new ArrayList<>();
        List<StraightLine> lines = new ArrayList<>();
        for (int i = lineEntities.size(); i < lineEntities.size(); i++) {
            DXFLine line = (DXFLine) lineEntities.get(i);
            StraightLine linePoint = new StraightLine();
            StraightLine.Coordinate start = StraightLine.Coordinate.getPointCoordinate(line.getStartPoint().getX(), line.getStartPoint().getY());
            StraightLine.Coordinate end = StraightLine.Coordinate.getPointCoordinate(line.getEndPoint().getX(), line.getEndPoint().getY());
            linePoint.setStart(start);
            linePoint.setEnd(end);
            lines.add(linePoint);
        }
        LinkedList<StraightLine> fixedLines = new LinkedList<>();
        StraightLine current = lines.remove(0);
        fixedLines.add(current);
        // 递归修正
        fixPolygon(lines, fixedLines, current);

        System.out.println(JSONUtil.toJsonStr(fixedLines));

        return list;
    }

    private List<DXFPointInfo> parseLine(List lineEntities) {
        List<DXFPointInfo> list = new ArrayList<>();
        int next = 0;
        do {
            List<StraightLine> linePoints = new ArrayList<>();
            // 解析线段关系组成几何图形
            next = parseLine2Geometry(next, lineEntities, linePoints);
            DXFPointInfo lineInfo = DXFPointInfo.builder().type("LINE").points(linePoints).build();
            if (!CollectionUtil.isEmpty(linePoints)) {
                // 计算外接矩形起点坐标和宽高
                List<BigDecimal> pointXList = lineInfo.getPoints().stream().map(point -> point.getStart().getX()).collect(Collectors.toList());
                List<BigDecimal> pointYList = lineInfo.getPoints().stream().map(point -> point.getStart().getY()).collect(Collectors.toList());
                Rectangle rectangle = getRectangle(pointXList, pointYList);
                lineInfo.setRectangle(rectangle);
                list.add(lineInfo);
            }
        } while (next != 0 && next < lineEntities.size());
        return list;
    }


    public static int parseLine2Geometry(int nextIndex, List lineEntities, List<StraightLine> linePoints) {
        for (int i = nextIndex; i < lineEntities.size(); i++) {
            DXFLine line = (DXFLine) lineEntities.get(i);
            StraightLine linePoint = new StraightLine();
            StraightLine.Coordinate start = StraightLine.Coordinate.getPointCoordinate(line.getStartPoint().getX(), line.getStartPoint().getY());
            StraightLine.Coordinate end = StraightLine.Coordinate.getPointCoordinate(line.getEndPoint().getX(), line.getEndPoint().getY());
            linePoint.setStart(start);
            linePoint.setEnd(end);
            //            linePoint.setStart(line.getStartPoint());
//            linePoint.setEnd(line.getEndPoint());
            // 第三条直线
            if (i >= nextIndex + 2) {
                // 判断当前直线与其他直线是否构成了闭合图形
                if (isClosed(line, linePoints)) {
                    linePoints.add(linePoint);
                    return i + 1;
                }
            }
            linePoints.add(linePoint);
        }
        throw new RuntimeException("存在非闭合图形,请确认图形是否正确");
    }

    /**
     * 判断是否可以构成闭合图形
     *
     * @param currLine
     * @param lineEntities
     * @return
     */
    public static boolean isClosed(DXFLine currLine, List lineEntities) {
        // 判断是否能够构成闭合图形
        List<String> points = new ArrayList<>();
        for (Object lineEntity : lineEntities) {
            StraightLine linePoint = (StraightLine) lineEntity;
            StraightLine.Coordinate startPoint = linePoint.getStart();
            StraightLine.Coordinate endPoint = linePoint.getEnd();
            points.add(startPoint.getX() + "#" + startPoint.getY());
            points.add(endPoint.getX() + "#" + endPoint.getY());
        }
        String currStartPoint = currLine.getStartPoint().getX() + "#" + currLine.getStartPoint().getY();
        String currentEndPoint = currLine.getEndPoint().getX() + "#" + currLine.getEndPoint().getY();
        return points.contains(currStartPoint) && points.contains(currentEndPoint);
    }
}
